package org.abratuhi.kvngroupware.server.model;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.util.Properties;

import org.abratuhi.kvngroupware.brainstorm.manager.BrainstormManager;
import org.abratuhi.kvngroupware.brainstorm.mptua.BrainstormRequestMessageProceeder;
import org.abratuhi.kvngroupware.chat.manager.ChatroomManager;
import org.abratuhi.kvngroupware.chat.mptua.ChatroomRequestMessageProceeder;
import org.abratuhi.kvngroupware.dalgen.DalgenRequestMessageProceeder;
import org.abratuhi.kvngroupware.jokemanager.manager.JokeManager;
import org.abratuhi.kvngroupware.jokemanager.mptua.JokemanagerRequestMessageProceeder;
import org.abratuhi.kvngroupware.login.mptua.LoginRequestMessageProceeder;
import org.abratuhi.kvngroupware.network.BasicRequestMessageProceeder;
import org.abratuhi.kvngroupware.network.Client;
import org.abratuhi.kvngroupware.network.Message;
import org.abratuhi.kvngroupware.network.MessageProceeder;
import org.abratuhi.kvngroupware.network.MessageSender;
import org.abratuhi.kvngroupware.network.Server;
import org.abratuhi.kvngroupware.registration.mptua.RegistrationRequestMessageProceeder;
import org.abratuhi.kvngroupware.scenario.manager.ScenarioManager;
import org.abratuhi.kvngroupware.scenario.mptua.ScenarioJokeRequestMessageProceeder;
import org.abratuhi.kvngroupware.scenario.mptua.ScenarioRequestMessageProceeder;
import org.abratuhi.kvngroupware.server.db.ServerDB;
import org.abratuhi.kvngroupware.server.mptua.ServerMPTUA;
import org.abratuhi.kvngroupware.team.manager.TeamManager;
import org.abratuhi.kvngroupware.team.mptua.TeamRequestMessageProceeder;
import org.abratuhi.kvngroupware.user.manager.UserManager;
import org.abratuhi.kvngroupware.user.mptua.UserRequestMessageProceeder;
import org.jdom.Element;

public class KVNGroupwareServer implements MessageProceeder, MessageSender{
	
	public final static String serverFile = "server.properties";
	
	Properties serverprops;
	
	UserManager usermanager = new UserManager();
	TeamManager teammanager = new TeamManager();
	ChatroomManager chatroommanager = new ChatroomManager();
	BrainstormManager brainstormmanager = new BrainstormManager();
	ScenarioManager scenariomanager = new ScenarioManager();
	JokeManager jokemanager = new JokeManager();
	
	BasicRequestMessageProceeder basicmproceeder = new BasicRequestMessageProceeder();
	RegistrationRequestMessageProceeder registrationmproceeder;
	LoginRequestMessageProceeder loginmproceeder;
	UserRequestMessageProceeder usermproceeder;
	TeamRequestMessageProceeder teammproceeder;
	ChatroomRequestMessageProceeder chatroommproceeder;
	BrainstormRequestMessageProceeder brainstormmproceeder;
	ScenarioRequestMessageProceeder scenariomproceeder;
	ScenarioJokeRequestMessageProceeder scenariojokemproceeder;
	JokemanagerRequestMessageProceeder jokemanagermproceeder;
	DalgenRequestMessageProceeder dalgenmproceeder;
	
	Server netserver;
	//ServerMPTUA mptua;
	ServerDB db;
	
	public KVNGroupwareServer(){
		this.serverprops = loadProperties(serverFile);
		this.netserver = new Server(this, Integer.valueOf(serverprops.getProperty("server.port")));
		//this.mptua = new ServerMPTUA(this);
		this.db = new ServerDB(this, serverprops);
		
		registrationmproceeder = new RegistrationRequestMessageProceeder(this, usermanager, teammanager, db);
		loginmproceeder = new LoginRequestMessageProceeder(this, usermanager, db);
		usermproceeder = new UserRequestMessageProceeder(this, usermanager, db);
		teammproceeder = new TeamRequestMessageProceeder(this, usermanager, teammanager, db);
		chatroommproceeder = new ChatroomRequestMessageProceeder(this, usermanager, chatroommanager, db);
		brainstormmproceeder = new BrainstormRequestMessageProceeder(this, usermanager, brainstormmanager, db);
		scenariomproceeder = new ScenarioRequestMessageProceeder(this, usermanager, scenariomanager, db);
		scenariojokemproceeder = new ScenarioJokeRequestMessageProceeder(this, usermanager, scenariomanager, db);
		jokemanagermproceeder = new JokemanagerRequestMessageProceeder(this, usermanager, jokemanager, db);
		dalgenmproceeder = new DalgenRequestMessageProceeder(this, this.serverprops);
	}
	
	//public ServerMPTUA getMPTUA(){
	//	return this.mptua;
	//}
	//public ServerDB getDB(){
	//	return this.db;
	//}
	
	public void start(){
		this.netserver.up();
		this.netserver.start();
	}
	
	public void stop(){
		this.netserver.stop();
		this.netserver.down();
	}
	
	public void clear(){
		usermanager.clear();
		chatroommanager.clear();
		brainstormmanager.clear();
		teammanager.clear();
		scenariomanager.clear();
	}
	
	public void exit(){
		System.exit(0);
	}
	
	/**/
	public String getSummary(){
		StringWriter sw = new StringWriter();
		sw.append("**************************************************"+"\n");
		sw.append("*************** GROUPWARE STATISTICS: ************"+"\n");
		sw.append("**************************************************"+"\n");
		
		sw.append("Users:\t");
		String[] users = usermanager.getkeys();
		for(int i=0; i<users.length;i++){
			sw.append(usermanager.get(users[i]).getId()+" ");
		}
		sw.append("\n");
		 
		sw.append("Brainstorms:\t");
		String[] brainstorms = brainstormmanager.getkeys();
		for(int i=0; i<brainstorms.length;i++){
			sw.append(brainstormmanager.get(brainstorms[i]).getSummary()+" ");
		}
		sw.append("\n");
		
		sw.append("Chatrooms:\t");
		String[] chatrooms = chatroommanager.getkeys();
		for(int i=0; i<chatrooms.length;i++){
			sw.append(chatroommanager.get(chatrooms[i]).getSummary()+" ");
		}
		sw.append("\n");
		
		return sw.toString();
	}
	
	public void proceedMessage(Client client, Message message) {
		//System.out.println("KVNGROUPWARE_CLIENT [recv]: "+message.toString());
		basicmproceeder.proceedMessage(client, message);
		registrationmproceeder.proceedMessage(client, message);
		loginmproceeder.proceedMessage(client, message);
		usermproceeder.proceedMessage(client, message);
		teammproceeder.proceedMessage(client, message);
		chatroommproceeder.proceedMessage(client, message);
		brainstormmproceeder.proceedMessage(client, message);
		scenariomproceeder.proceedMessage(client, message);
		scenariojokemproceeder.proceedMessage(client, message);
		jokemanagermproceeder.proceedMessage(client, message);
		dalgenmproceeder.proceedMessage(client, message);
		//mptua.proceedMessage(message);
	}
	
	public Message createMessage(String[] attrs, String[] values, String text, Element[] contents){
		Message message = new Message();
		//Element from = new Element("from");
		//from.setAttribute("type", "uid");
		//from.setAttribute("id", "system");
		//Element to = new Element("to");
		//to.setAttribute("type", "uid");
		//to.setAttribute("id", "*");
		Element response = new Element("response");
		response.setText(text);
		for(int i=0; i<contents.length; i++)
			response.addContent(contents[i]);
		for(int i=0; i<attrs.length; i++)
			response.setAttribute(attrs[i], values[i]);
		//message.getRoot().addContent(from);
		//message.getRoot().addContent(to);
		message.getRoot().addContent(response);
		return message;
	}
	
	public Message createMessage(String attrs, String values, String text, Element[] contents){
		return createMessage(attrs.split(","), values.split(","), text, contents);
	}
	
	public void sendMessage(Message message, String[] recipients){
		if(recipients != null){
		for(int i=0; i<recipients.length; i++){
			if(recipients[i] != null){
				System.out.println("Sent["+recipients[i]+"]: "+message.toString());
				netserver.getClient(recipients[i]).sendMessage(message);
			}
		}
		}
	}

	@Override
	public void sendMessage(Message message) {
		String[] recipients = netserver.getClientIds();
		sendMessage(message, recipients);
	}

	
	public Properties loadProperties(String file){
		Properties props = new Properties();
		try {
			if(file.endsWith(".xml")){
		        props.loadFromXML(new FileInputStream(file));
			}
			else if(file.endsWith(".properties") || file.endsWith(".preferences")){
				props.load(new FileInputStream(file));
			}
	    } catch (IOException e) {
	    	e.printStackTrace();
	    }
	    return props;
	}
	
	public static void main(String[] args){
		KVNGroupwareServer kvnserver = new KVNGroupwareServer();
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		
		while(true){
			System.out.print("cmdsh > ");
			try {
				String command = in.readLine();
				if(command.equals("quit")){
					kvnserver.exit();
					break;
				}
				else if(command.equals("start")){
					kvnserver.start();
				}
				else if(command.equals("stop")){
					kvnserver.stop();
				}
				else if(command.equals("info")){
					System.out.println(kvnserver.netserver.getSummary());
					System.out.println(kvnserver.getSummary());
				}
				else if(command.equals("clear")){
					kvnserver.clear();
				}
				else if(command.equals("help")){
					System.out.println("Recognized commandos:\nstart\nstop\ninfo\nhelp\nquit");
				}
				else{
					System.out.println("'"+command+"': Unrecognized command, print 'help' to get the list available commandos.");
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}
